﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using GlassStore.Models;
using System.IO;
using GlassStore.Helpers;
using GlassStore.ViewModels;
using System.Drawing;

namespace GlassStore.Controllers
{
    [Authorize(Roles="Administrator")]
    public class GlassManagerController : Controller
    {
      GlassStoreEntities storeDB = new GlassStoreEntities();
      GlassHelper glassHelper = new GlassHelper();
      private int pagesize = 10;
        //
        // GET: /GlassManager?id=1
        public ActionResult Index(int?id)
      {
          int index = id.HasValue ? id.Value : 1;
          var glasses = storeDB.Glasses;
          var viewModel = new GlassBrowseViewModel
          {
              Glasses = glasses.OrderBy(g => g.GlassId).Skip((index - 1) * pagesize).Take(pagesize).ToList(),
              Index = index,
              Total = (glasses.Count() - 1) / pagesize + 1,
          };
          return View(viewModel);
        }

        //
        // GET: /GlassManager/Details/5

        public ActionResult Details(int id)
        {
          var glass = storeDB.Glasses.Include("GlassPictures").Single(g=>g.GlassId == id);
          return View(glass);
        }

        //
        // GET: /GlassManager/Create

        public ActionResult Create()
        {
            var glassManagerViewModel = new GlassManagerViewModel
            {
                Glass = new Glass(),
                TopCatalogues = storeDB.TopCatalogues.Include("SubCatalogues").ToList(),
                MaterialList = glassHelper.GetMaterialList(),
                StyleList = glassHelper.GetStyleList(),
                OpticsGlasses = glassHelper.GetOpticsGlasses(),
                SunGlasses = glassHelper.GetSunGlasses(),
            };
            return View(glassManagerViewModel);
        } 

        //
        // POST: /GlassManager/Create

        [HttpPost]
        public ActionResult Create(Glass glass)
        {
          if (ModelState.IsValid)
          {
              // pictures
            HandlePictureUpload(glass);

              //catalogue
            HandleGlassCatalogue(glass);

            glass.CreateTime = DateTime.Now;

            storeDB.AddToGlasses(glass);
            storeDB.SaveChanges();

            return RedirectToAction("Index");
          }
          else
          {
            return View(glass);
          }
        }

        private void HandlePictureUpload(Glass glass)
        {
          foreach (string upload in Request.Files)
          {
                  if (Request.Files[upload].ContentLength == 0)
                      continue;
                  string path = string.Format("{0}uploads/{1}/", AppDomain.CurrentDomain.BaseDirectory, FileUploadHelpers.GlassDir);
                  if (!Directory.Exists(path))
                      Directory.CreateDirectory(path);

                  string generatedFilename = FileUploadHelpers.GenerateFileName();
                  string fileName = generatedFilename + Path.GetExtension(Request.Files[upload].FileName);
                  Request.Files[upload].SaveAs(Path.Combine(path, fileName));
                  string url = string.Format("/uploads/{0}/{1}", FileUploadHelpers.GlassDir, fileName);

                  if (upload == "ThumbnailUpload")
                  {
                      // delete original thumbnail
                      DeleteFileFromUrl(glass.Thumbnail);
                      // delete original thumbnail smaller size
                      DeleteFileFromUrl(glass.ThumbnailSmall);

                      glass.Thumbnail = url;

                      // resize thumbnail
                      string fileNameResize = generatedFilename + "_resize" + Path.GetExtension(Request.Files[0].FileName);
                      if (ResizeImage(Path.Combine(path, fileName), Path.Combine(path, fileNameResize), 160, 160))
                      {
                          glass.ThumbnailSmall = string.Format("/uploads/{0}/{1}", FileUploadHelpers.GlassDir, fileNameResize);
                      }
                  }
                  else
                  {
                      glass.GlassPictures.Add(new GlassPicture { PictureURL = url });
                  }
          }
        }

        private void HandleGlassCatalogue(Glass glass)
        {
          //catalogue
          if (this.Request.Form["SelectedCatalogue"] != null)
          {
            var ids = this.Request.Form["SelectedCatalogue"].Split(new char[] { ',' });
            foreach (string idString in ids)
            {
              int cid = int.Parse(idString);
              glass.GlassCatalogues.Add(new GlassCatalogue { GlassId = glass.GlassId, SubCatalogueId = cid });
            }
          }
        }
        
        //
        // GET: /GlassManager/Edit/5
 
        public ActionResult Edit(int id)
        {
          var glassManagerViewModel = new GlassManagerViewModel
          {
            Glass = storeDB.Glasses.Include("GlassCatalogues").Single(g => g.GlassId == id),
            TopCatalogues = storeDB.TopCatalogues.Include("SubCatalogues").ToList(),
            MaterialList = glassHelper.GetMaterialList(),
            StyleList = glassHelper.GetStyleList(),
            OpticsGlasses = glassHelper.GetOpticsGlasses(),
            SunGlasses = glassHelper.GetSunGlasses(),
          };
          return View(glassManagerViewModel);
        }

        //
        // POST: /GlassManager/Edit/5

        [HttpPost]
        public ActionResult Edit(int id, FormCollection collection)
        {
          var glass = storeDB.Glasses.Include("GlassPictures").Include("GlassCatalogues").Single(t => t.GlassId == id);
          try
          {
            UpdateModel(glass, "Glass");

            // add picture
            HandlePictureUpload(glass);

            // delete picture
            if (collection["DeletedPictureId"] != null)
            {
              var ids = collection["DeletedPictureId"].Split(new char[]{','});
              foreach (string idString in ids)
              {
                int pid = int.Parse(idString);

                var picture = glass.GlassPictures.Single(p => p.PictureId == pid);
                if (picture == null)
                  continue;

                // delete picture file
                if (!string.IsNullOrEmpty(picture.PictureURL))
                {
                  string fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, picture.PictureURL.Remove(0, 1));
                  try
                  {
                    System.IO.File.Delete(fileName);
                  }
                  catch
                  {
                  }
                }
                glass.GlassPictures.Remove(picture);
                // !!!this statement is very importment, the following exception raise if missing
                // The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
                storeDB.GlassPictures.DeleteObject(picture);
              }
            }

            //catalogue
            foreach (var gc in glass.GlassCatalogues.ToList())
            {
              glass.GlassCatalogues.Remove(gc);
              storeDB.GlassCatalogues.DeleteObject(gc);
            }
            HandleGlassCatalogue(glass);

            storeDB.SaveChanges();

            return RedirectToAction("Index");
          }
          catch
          {
            return View(glass);
          }
        }

        //
        // GET: /GlassManager/Delete/5
 
        public ActionResult Delete(int id)
        {
          var glass = storeDB.Glasses.Single(g => g.GlassId == id);
          return View(glass);
        }

        //
        // POST: /GlassManager/Delete/5

        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
          try
          {
            // !!! Include is very important, the following exception raised if missing
            // The DELETE statement conflicted with the REFERENCE constraint
            var glass = storeDB.Glasses.Include("GlassPictures").Include("GlassCatalogues").Single(g => g.GlassId == id);
            storeDB.DeleteObject(glass);
            storeDB.SaveChanges();

            return View("Deleted");
          }
          catch
          {
            return View("Index");
          }
        }

        private bool ResizeImage(string srcFile, string destFile, int newWidth, int newHeight)
        {
            try
            {
                var bitmap = new Bitmap(srcFile);
                var newBitmap = Helpers.ImageHelper.ResizeBitmap(bitmap, newWidth, newHeight);
                if (newBitmap == null)
                    return false;

                newBitmap.Save(destFile);
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        private void DeleteFileFromUrl(string url)
        {
            if (!string.IsNullOrEmpty(url))
            {
                string fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, url.Remove(0, 1));
                try
                {
                    if (System.IO.File.Exists(fileName))
                    {
                        System.IO.File.Delete(fileName);
                    }
                }
                catch
                {
                }
            }
        }
    }
}
